import json
import logging
import pdb
from PIL import Image
from io import BytesIO
from bs4 import BeautifulSoup
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.core.files.base import ContentFile
from django.http import HttpResponseRedirect, HttpResponse
from django.http.response import StreamingHttpResponse, JsonResponse
from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.decorators import permission_classes, api_view, action
from rest_framework.generics import get_object_or_404
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import IsAuthenticated, AllowAny, DjangoModelPermissions
from rest_framework.response import Response
from rest_framework import status
from django.core.paginator import Paginator
from django.core import serializers
from rest_framework.views import APIView

from .models import News
from .serializers import PartnersSerializer, ProductSerializer, NewsSerializer, HonourSerializer, SimpleNewsSerializer, \
    NewsListSerializer, ProjectSerializer
import xlrd
import xlwt
import uuid
from django.db import transaction
from . import models
from huadijianshe_website.settings import MEDIA_ROOT
from django.db.models import Q
import os
from urllib.parse import quote
from huadijianshe_website.settings import BASE_DIR

logger = logging.getLogger('django')


def auth_login(request):
    if request.method == 'GET':
        if request.user.is_authenticated:
            return HttpResponseRedirect('/console')
        else:
            return render(request, 'admin/login.html')
    elif request.method == 'POST':
        next = request.POST.get('next', '/console')
        username = request.POST.get('username')
        password = request.POST.get('password')
        user = authenticate(username=username, password=password)
        if user is not None and user.is_active:
            login(request, user)
            if not request.POST.get('remember_me', None):
                request.session.set_expiry(0)
            if next:
                return HttpResponseRedirect(next)
            else:
                return HttpResponseRedirect('/console')
        else:
            message = "用户名不存在或密码错误!"
            return render(request, 'admin/login.html', {'message': message})


def auth_logout(request):
    if request.method == 'POST':
        logout(request)
        return render(request, 'admin/login.html')


@login_required()
def products(request):
    return render(request, 'admin/products.html')


@login_required()
def orders(request):
    return render(request, 'admin/orders.html')


def product_search(request):
    return render(request, 'productSearch.html')


def product_details(request):
    return render(request, 'ProductDetails.html')


def news_details(request):
    return render(request, 'newsDetails.html')


def dynamic_details(request):
    return render(request, 'dynamicDetails.html')


@login_required()
def partners(request):
    return render(request, 'admin/partners.html')


@login_required()
def qualifications(request):
    return render(request, 'admin/certificates/qualifications.html')


@login_required()
def honours(request):
    return render(request, 'admin/certificates/honours.html')


@login_required()
def news_list(request):
    news_items = models.News.objects.all().order_by('-publish_date')
    return render(request, 'admin/news_list.html', {'news_items': news_items})


@login_required()
def project_updates(request):
    news_items = models.News.objects.all().order_by('-publish_date')
    return render(request, 'admin/project_updates.html', {'news_items': news_items})


@login_required()
def project_list(request):
    return render(request, 'admin/project_list.html')


@api_view(['GET'])
@login_required()
def news_list_api(request):
    news_items = models.News.objects.all().order_by('-publish_date')
    serializer = serializers.NewsSerializer(news_items, many=True)
    return Response(serializer.data)


from django.utils import timezone
import json


@login_required()
def add_news(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            title = data.get('title')
            content = data.get('content')
            cover_image_url = data.get('cover_image_url')
            news_type = data.get('type', 'performance')  # 默认类型为 'performance'

            # 尝试获取前端提供的 publish_date，如果没有则使用默认日期
            publish_date_str = data.get('publish_date')
            if publish_date_str:
                try:
                    # 假设日期格式为 'yyyy-mm-dd'，根据需要调整格式解析
                    publish_date = timezone.datetime.strptime(publish_date_str, '%Y-%m-%d').date()
                except ValueError:
                    return JsonResponse({'error': 'Invalid date format'}, status=400)
            else:
                publish_date = timezone.now().date()

            # 创建新闻对象
            models.News.objects.create(
                title=title,
                content=content,
                publish_date=publish_date,
                cover_image_url=cover_image_url,
                type=news_type  # 添加 type 字段
            )

            return JsonResponse({'message': 'News created successfully'}, status=201)

        except json.JSONDecodeError:
            return JsonResponse({'error': 'Invalid JSON'}, status=400)

        except Exception as e:
            # 捕获其他异常并返回错误信息
            return JsonResponse({'error': str(e)}, status=400)

    # 如果不是 POST 请求，返回一个简单的页面
    return render(request, 'admin/add_news.html')


@login_required()
def edit_news(request, pk):
    news_item = get_object_or_404(models.News, id=pk)
    if request.method == 'POST':
        news_item.title = request.POST.get('title')
        news_item.content = request.POST.get('content')
        news_item.save()
        return HttpResponseRedirect('/console/news/')
    return render(request, 'admin/edit_news.html', {'news_item': news_item})


def about_abcarta(request):
    partners_info = models.Partners.objects.filter(~Q(partners_logo=None)
                                                   & ~Q(partners_logo='')).values('partners_logo',
                                                                                  'partners_url',
                                                                                  'partners')
    return render(request, 'HomePage.html', locals())


def honour(request):
    return render(request, 'honour.html')


def about_us(request):
    return render(request, 'about_us.html')


def business(request):
    return render(request, 'business.html')


def contact_us(request):
    return render(request, 'contact_us.html')


def news(request):
    return render(request, 'news.html')


def dynamic(request):
    return render(request, 'dynamic.html')


def core_product(request):
    return render(request, 'CoreProduct.html')


def machine_detail(request):
    return render(request, 'MachineDetail.html')


def research_cooperation(request):
    return render(request, 'ResearchCooperation.html')


def product_service(request):
    return render(request, 'ProductService.html')


@permission_classes((AllowAny,))
class ProductsSearchViewSet(viewsets.ViewSet):
    def list(self, request):
        context = {"recordsTotal": 0, "recordsFiltered": 0, "totalPage": 1, 'data': [{}]}
        nav = request.GET.get('nav')
        page = request.GET.get('page', 1)
        queryString = request.GET.get('query')
        if nav:
            nav = nav.split("-")
            if queryString == None or queryString.replace(" ", "") == "":
                products = Paginator(
                    models.Products.objects.filter(Q(name__istartswith=nav[0]) | Q(name__istartswith=nav[1])).order_by(
                        'id'), 30)
            else:
                products = Paginator(models.Products.objects.filter(
                    (Q(name__istartswith=nav[0]) | Q(name__istartswith=nav[1])) & Q(
                        name__icontains=queryString)).order_by('id'), 30)
            total_count = products.count
            if total_count == 0:
                return Response(context)
            products_json = json.loads(serializers.serialize('json', products.page(page)))
            products_list = []
            count = 1
            product_group = {}
            for _product in products_json:
                if count % 3 == 1:
                    product_group["col_1_name"] = _product.get('fields').get('name')
                    product_group["col_1_item_num"] = _product.get('fields').get('item_num')
                    count = count + 1
                elif count % 3 == 2:
                    product_group["col_2_name"] = _product.get('fields').get('name')
                    product_group["col_2_item_num"] = _product.get('fields').get('item_num')
                    count = count + 1
                elif count % 3 == 0:
                    product_group["col_3_name"] = _product.get('fields').get('name')
                    product_group["col_3_item_num"] = _product.get('fields').get('item_num')
                    products_list.append(product_group)
                    product_group = {}
                    count = count + 1
                if count - 1 == len(products_json) and (count - 1) % 3 != 0:
                    products_list.append(product_group)
            if total_count % 30 == 0:
                total_page = total_count // 30
            else:
                total_page = total_count // 30 + 1
            context = {"recordsTotal": total_count, "recordsFiltered": total_count, "totalPage": total_page,
                       'data': products_list}
        return Response(context)


@permission_classes((AllowAny,))
class ProductDetailViewSet(viewsets.ViewSet):
    def list(self, request):
        item_num = request.GET.get('item_num')
        product_obj = models.Products.objects.filter(item_num=item_num)
        order_obj = models.Orders.objects.filter(product_item_num=item_num)
        product_json = json.loads(serializers.serialize('json', product_obj))
        order_json = json.loads(serializers.serialize('json', order_obj))
        context = {'data': product_json, 'order_data': order_json}
        return Response(context)


@permission_classes((AllowAny,))
class NewsDetailViewSet(viewsets.ReadOnlyModelViewSet):
    """
    A simple ViewSet for viewing the details of a single News item.
    """

    queryset = models.News.objects.all().order_by('-publish_date')
    serializer_class = NewsSerializer
    permission_classes = [AllowAny]

    # 您可以覆盖 retrieve 方法以自定义其行为
    def retrieve(self, request, pk=None):
        """
        Retrieves a single news item based on its primary key (pk).
        """
        news_item = get_object_or_404(self.queryset, pk=pk)
        serializer = self.get_serializer(news_item)
        return Response(serializer.data)


@permission_classes((IsAuthenticated,))
class OrdersViewSet(viewsets.ViewSet):

    def list(self, request):
        start = request.GET.get('start')
        length = request.GET.get('length')
        filter_content = request.GET.get('search[value]')
        page = int((int(start) + int(length)) / int(length))
        if filter_content != '':
            filter_condition = filter_content.split('=')[1]
            if filter_condition == '':
                orders_obj = Paginator(models.Orders.objects.all().order_by('id'), int(length))
            else:
                if "-" in filter_condition:
                    orders_obj = Paginator(models.Orders.objects.filter(
                        Q(product_item_num__icontains=filter_condition.split("-")[0]) | Q(
                            sub_item_num__icontains=filter_condition.split("-")[1])).order_by(
                        'id'), int(length))
                else:
                    orders_obj = Paginator(models.Orders.objects.filter(
                        Q(product_item_num__icontains=filter_condition) | Q(
                            sub_item_num__icontains=filter_condition) | Q(
                            product_type__icontains=filter_condition)).order_by(
                        'id'), int(length))
        else:
            orders_obj = Paginator(models.Orders.objects.all().order_by('id'), int(length))
        orders_json = json.loads(serializers.serialize('json', orders_obj.page(page)))
        total_count = orders_obj.count
        context = {"recordsTotal": total_count, "recordsFiltered": total_count, 'data': orders_json}
        return Response(context)

    def create(self, request):
        product_item_num = request.data.get('product_item_num', '')
        sub_item_num = request.data.get('sub_item_num', '')
        flavor = request.data.get('flavor', '')
        unit = request.data.get('unit', '')
        product_type = request.data.get('product_type', '')
        models.Orders.objects.update_or_create(
            defaults={
                "flavor": flavor.strip(),
                "unit": unit.strip(),
                "product_type": product_type.strip()
            },
            product_item_num=product_item_num.strip(),
            sub_item_num=sub_item_num.strip())
        return Response("ok")

    def update(self, request, pk=None):
        product_item_num = request.data.get('product_item_num', '')
        sub_item_num = request.data.get('sub_item_num', '')
        flavor = request.data.get('flavor', '')
        unit = request.data.get('unit', '')
        product_type = request.data.get('product_type', '')
        models.Orders.objects.update_or_create(defaults={
            "product_item_num": product_item_num.strip(),
            "sub_item_num": sub_item_num.strip(),
            "flavor": flavor.strip(),
            "unit": unit.strip(),
            "product_type": product_type.strip(),
        }, id=pk)
        return Response("ok")

    def destroy(self, request, pk=None):
        models.Orders.objects.filter(id=pk).delete()
        return Response("ok")


@permission_classes((IsAuthenticated,))
class ProductsViewSet(viewsets.ViewSet):

    def list(self, request):
        start = request.GET.get('start')
        length = request.GET.get('length')
        filter_content = request.GET.get('search[value]')
        page = int((int(start) + int(length)) / int(length))
        if filter_content != '':
            filter_condition = filter_content.split('=')[1]
            if filter_condition == '':
                products_obj = Paginator(models.Products.objects.all().order_by('id'), int(length))
            else:
                products_obj = Paginator(models.Products.objects.filter(
                    Q(name__icontains=filter_condition) | Q(item_num__icontains=filter_condition) | Q(
                        antibody_type__icontains=filter_condition) | Q(uni_prot__icontains=filter_condition) | Q(
                        clone_num__icontains=filter_condition) | Q(positive_part__icontains=filter_condition)).order_by(
                    'id'), int(length))
        else:
            products_obj = Paginator(models.Products.objects.all().order_by('id'), int(length))
        products_json = json.loads(serializers.serialize('json', products_obj.page(page)))
        total_count = products_obj.count
        context = {"recordsTotal": total_count, "recordsFiltered": total_count, 'data': products_json}
        return Response(context)

    def create(self, request):
        product_name = request.data.get('product_name', '')
        item_num = request.data.get('item_num', '')
        uni_prot = request.data.get('uni_prot', '')
        antibody_type = request.data.get('antibody_type', '')
        molecular_weight = request.data.get('molecular_weight', '')
        positive_part = request.data.get('positive_part', '')
        pretreatment = request.data.get('pretreatment', '')
        clone_num = request.data.get('clone_num', '')
        storage_validity_period = request.data.get('storage_validity_period', '')
        description = request.data.get('description', '')
        experimental_program = request.data.get('experimental_program', '')
        remarks = request.data.get('remarks', '')
        models.Products.objects.create(name=product_name.strip(),
                                       item_num=item_num.strip(),
                                       uni_prot=uni_prot.strip(),
                                       antibody_type=antibody_type.strip(),
                                       molecular_weight=molecular_weight.strip(),
                                       positive_part=positive_part.strip(),
                                       pretreatment=pretreatment.strip(),
                                       clone_num=clone_num.strip(),
                                       storage_validity_period=storage_validity_period.strip(),
                                       description=description.strip(),
                                       experimental_program=experimental_program.strip(),
                                       remarks=remarks.strip())
        return Response("ok")

    def update(self, request, pk=None):
        product_name = request.data.get('product_name', '')
        item_num = request.data.get('item_num', '')
        uni_prot = request.data.get('uni_prot', '')
        antibody_type = request.data.get('antibody_type', '')
        molecular_weight = request.data.get('molecular_weight', '')
        positive_part = request.data.get('positive_part', '')
        pretreatment = request.data.get('pretreatment', '')
        clone_num = request.data.get('clone_num', '')
        storage_validity_period = request.data.get('storage_validity_period', '')
        description = request.data.get('description', '')
        experimental_program = request.data.get('experimental_program', '')
        remarks = request.data.get('remarks', '')
        models.Products.objects.update_or_create(defaults={
            "name": product_name.strip(),
            "item_num": item_num.strip(),
            "uni_prot": uni_prot.strip(),
            "antibody_type": antibody_type.strip(),
            "molecular_weight": molecular_weight.strip(),
            "positive_part": positive_part.strip(),
            "pretreatment": pretreatment.strip(),
            "clone_num": clone_num.strip(),
            "storage_validity_period": storage_validity_period.strip(),
            "description": description.strip(),
            "experimental_program": experimental_program.strip(),
            "remarks": remarks.strip()
        }, id=pk)
        return Response("ok")

    def destroy(self, request, pk=None):
        models.Products.objects.filter(id=pk).delete()
        return Response("ok")


@permission_classes((IsAuthenticated,))
class DataProcessesViewSet(viewsets.ViewSet):

    def list(self, request):
        # 创建工作簿
        action = request.GET.get("action")
        wb = xlwt.Workbook(encoding='utf-8')
        # 创建表
        ws = wb.add_sheet('sheet1')
        row_num = 0
        font_style = xlwt.XFStyle()
        # 二进制
        font_style.font.bold = True
        file_path = BASE_DIR + "/download/products.xlsx"  # 储存路径
        filename = "products.xls"
        # 表头内容
        if "Product" in action:
            columns = ['产品名称', '货号', 'UniProt', '抗体类型', '分子量', '阳性部位', '预处理', '克隆号', '存储条件及有效期', '描述', '备注', '实验方案']
        elif "Order" in action:
            columns = ['产品货号', '子货号', '规格', '单位', '产品类型']
        # 写进表头内容
        for col_num in range(len(columns)):
            ws.write(row_num, col_num, columns[col_num], font_style)
        if action == "downloadProductAllData":
            rows = models.Products.objects.all().values_list('name', 'item_num', 'uni_prot', 'antibody_type',
                                                             'molecular_weight', 'positive_part', 'pretreatment',
                                                             'clone_num', 'storage_validity_period', 'description',
                                                             'remarks', 'experimental_program')
            # 遍历提取出来的内容
            font_style.font.bold = False
            for row in rows:
                row_num += 1
                # 逐行写入Excel
                for col_num in range(len(columns)):
                    ws.write(row_num, col_num, row[col_num], font_style)
        elif action == "downloadProductTemplate":
            file_path = BASE_DIR + "/download/products-template.xlsx"
            filename = "products-template.xls"
        elif action == "downloadOrderTemplate":
            file_path = BASE_DIR + "/download/orders-template.xlsx"
            filename = "orders-template.xls"
        wb.save(file_path)

        # 利用生成器进行文件读取
        def iter_file(path):
            size = 1024
            with open(path, "rb") as f:
                for data in iter(lambda: f.read(size), b''):
                    yield data

        # 以二进制形式进行数据流传输

        response = StreamingHttpResponse(iter_file(file_path))  # 以二进制形式响应数据流
        response['Content-Type'] = 'application/octet-stream'  # 浏览器不识别的也会自动下载
        response['Content-Disposition'] = 'attachment; {}'.format(
            "filename*=utf-8''{}".format(quote(filename)))  # quote确保中文格式不乱码
        return response

    def create(self, request):
        type = request.data.get('type')
        f = request.FILES.get('file')
        excel_type = f.name.split('.')[1]
        if excel_type in ['xlsx', 'xls']:
            # 开始解析上传的excel表格
            wb = xlrd.open_workbook(filename=None, file_contents=f.read())
            table = wb.sheets()[0]
            rows = table.nrows  # 总行数
            try:
                with transaction.atomic():
                    for i in range(1, rows):
                        rowVlaues = table.row_values(i)
                        if type == "products":
                            models.Products.objects.update_or_create(
                                defaults={
                                    "name": rowVlaues[0].strip(),
                                    "uni_prot": rowVlaues[2].strip(),
                                    "antibody_type": rowVlaues[3].strip(),
                                    "molecular_weight": rowVlaues[4].strip(),
                                    "positive_part": rowVlaues[5].strip(),
                                    "pretreatment": rowVlaues[6].strip(),
                                    "clone_num": rowVlaues[7].strip(),
                                    "storage_validity_period": rowVlaues[8].strip(),
                                    "description": rowVlaues[9].strip(),
                                    "remarks": rowVlaues[10].strip(),
                                    "experimental_program": rowVlaues[11].strip()
                                },
                                item_num=rowVlaues[1].strip()
                            )
                        elif type == "orders":
                            count = models.Products.objects.filter(item_num=rowVlaues[0].strip()).count()
                            if count == 1:
                                models.Orders.objects.update_or_create(
                                    defaults={
                                        "flavor": rowVlaues[2].strip(),
                                        "unit": rowVlaues[3].strip(),
                                        "product_type": rowVlaues[4].strip()
                                    },
                                    product_item_num=rowVlaues[0].strip(),
                                    sub_item_num=rowVlaues[1].strip()
                                )
                            logger.warning("货号" + rowVlaues[0].strip() + "不存在，已跳过")
            except Exception as e:
                logger.error(e)
                logger.error('解析excel文件或者数据插入错误')
                return Response({"code": "500", "msg": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            return Response({"code": 200, "msg": "上传成功"})
        else:
            logger.error('上传文件类型错误！')
            return Response(data={"code": 400, "msg": "上传文件格式错误！"}, status=status.HTTP_400_BAD_REQUEST)


@permission_classes((IsAuthenticated,))
class ProductImagesViewSet(viewsets.ViewSet):
    def list(self, request):
        # 实现list方法以返回产品图片信息（如果需要）
        pass

    def create(self, request):
        try:
            imgs = request.FILES.getlist('file')
            product_id = request.data.get('product_id')
            product_image_list = []

            for item in imgs:
                # 为每个图像生成唯一的文件名
                img_name = str(uuid.uuid4()) + "." + item.name.split('.')[-1]
                img_url = "/media/product_images/" + img_name
                product_image_list.append(img_url)

                # 确保目录存在
                os.makedirs(MEDIA_ROOT + "/product_images/", exist_ok=True)

                # 打开原始图像并进行压缩
                image = Image.open(item)
                image_io = BytesIO()
                image.save(image_io, format=image.format, quality=70)  # 设置压缩质量为70%
                compressed_image = ContentFile(image_io.getvalue(), name=img_name)

                # 保存压缩后的图像
                with open(MEDIA_ROOT + "/product_images/" + img_name, 'wb') as f:
                    f.write(compressed_image.read())

            # 更新产品图片列表
            product = models.Products.objects.get(id=product_id)
            product.product_images_list = product_image_list
            product.save()

            return Response("ok", status=status.HTTP_201_CREATED)
        except Exception as e:
            print(f"Error: {e}")
            return Response(status=status.HTTP_400_BAD_REQUEST)


@permission_classes((IsAuthenticated,))
class PdfProcessViewSet(viewsets.ViewSet):
    def list(self, request):
        pass

    def create(self, request):
        try:
            pdf = request.FILES.getlist('file')
            product_id = request.data.get('product_id')
            pdf_url = ""
            for item in pdf:
                pdf_name = str(uuid.uuid4()) + "." + item.name.split('.')[1]
                pdf_url = "/guidebook/" + pdf_name
                with open(MEDIA_ROOT + "/guidebook/" + pdf_name, 'wb') as f:
                    for c in item.chunks():
                        f.write(c)
            product = models.Products.objects.get(id=product_id)
            product.product_guide_book = "/media" + pdf_url
            product.save()
        except Exception as e:
            logger.error(e)
            return Response({"code": "500", "msg": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        return Response({"code": 200, "msg": "导入成功"})


@permission_classes((AllowAny,))
class PartnersManageViewSet(viewsets.ModelViewSet):
    queryset = models.Partners.objects.all().order_by('-create_time')
    serializer_class = PartnersSerializer


class CustomPagination(PageNumberPagination):
    page_size_query_param = 'size'  # 允许前端客户端通过 `size` 参数控制每页条目数量
    page_query_param = 'page'  # 默认情况下，DRF 已经支持 `page` 参数用于分页
    max_page_size = 100  # 设置最大页大小来限制每页最多返回的条目数


@permission_classes((AllowAny,))
class HonourManageViewSet(viewsets.ModelViewSet):
    filterset_fields = ['honour_type']
    queryset = models.Honour.objects.all().order_by('-award_date')
    serializer_class = HonourSerializer
    pagination_class = CustomPagination  # 使用自定义分页类


class CustomPageNumberPagination(PageNumberPagination):
    page_size = 10  # 每页显示的对象数

    def get_paginated_response(self, data):
        return Response({
            'links': {
                'next': self.get_next_link(),
                'previous': self.get_previous_link()
            },
            'count': self.page.paginator.count,
            'total_pages': self.page.paginator.num_pages,
            'current_page': self.page.number,
            'results': data
        })


class NewsManageViewSet(viewsets.ModelViewSet):
    queryset = News.objects.all().order_by('-publish_date')
    serializer_class = NewsListSerializer
    permission_classes = [AllowAny]
    pagination_class = CustomPageNumberPagination

    def get_queryset(self):
        # 只在列表请求时过滤类型
        if self.action == 'list':
            news_type = self.request.query_params.get('type', 'performance')
            return News.objects.filter(type=news_type).order_by('-publish_date')
        return super().get_queryset()

    def get_serializer_class(self):
        if self.action == 'list':
            return NewsListSerializer
        return NewsSerializer  # 其他操作使用完整序列化器

    def destroy(self, request, *args, **kwargs):
        # 重写删除方法确保不进行类型过滤
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)


# 然后在视图集中使用这个自定义分页类
class ProjectManageViewSet(viewsets.ModelViewSet):
    queryset = models.Project.objects.all().order_by('-create_time')
    serializer_class = ProjectSerializer  # 使用自定义的序列化器
    permission_classes = [AllowAny]
    pagination_class = CustomPageNumberPagination  # 使用自定义分页


@permission_classes((AllowAny,))
class NewsDetailWithNavigation(APIView):
    permission_classes = [DjangoModelPermissions]

    def get_queryset(self):
        return News.objects.all().order_by('-publish_date')

    def get(self, request, pk, format=None):
        # 获取当前新闻对象
        news_item = get_object_or_404(News, pk=pk)
        news_item.increment_view_count()

        # 序列化当前新闻对象
        current_news_data = NewsSerializer(news_item).data

        # 获取同类型新闻并按时间排序
        same_type_news = News.objects.filter(
            type=news_item.type
        ).order_by('publish_date')

        # 转换为列表并找到当前索引
        same_type_list = list(same_type_news)
        try:
            current_index = same_type_list.index(news_item)
        except ValueError:
            current_index = None

        # 初始化导航数据
        previous_news_data = None
        next_news_data = None

        # 获取相邻新闻的逻辑
        if current_index is not None:
            # 前一条（时间更早）
            if current_index > 0:
                previous_news = same_type_list[current_index - 1]
                previous_news_data = SimpleNewsSerializer(previous_news).data

            # 后一条（时间更晚）
            if current_index < len(same_type_list) - 1:
                next_news = same_type_list[current_index + 1]
                next_news_data = SimpleNewsSerializer(next_news).data

        response_data = {
            **current_news_data,
            'previous': previous_news_data,
            'next': next_news_data
        }

        return Response(response_data, status=status.HTTP_200_OK)


@permission_classes((IsAuthenticated,))
class PartnerImagesViewSet(viewsets.ViewSet):
    def create(self, request):
        try:
            img = request.FILES.getlist('file')[0]
            partner_id = request.data.get('id')
            partner_info = models.Partners.objects.get(id=partner_id)
            partner_name = partner_info.partners

            # 使用 UUID 来生成唯一的文件名
            unique_filename = str(uuid.uuid4())
            extension = os.path.splitext(img.name)[1]  # 获取文件扩展名
            img_name = f"{partner_name}_{unique_filename}{extension}"
            img_url = f"/media/partners/{img_name}"

            # 确保目录存在
            os.makedirs(MEDIA_ROOT + "/partners/", exist_ok=True)

            # 打开原始图像并进行压缩
            image = Image.open(img)
            image_io = BytesIO()
            image.save(image_io, format=image.format, quality=70)  # 设置压缩质量为70%
            compressed_image = ContentFile(image_io.getvalue(), name=img_name)

            # 保存压缩后的图像
            with open(MEDIA_ROOT + "/partners/" + img_name, 'wb') as f:
                f.write(compressed_image.read())

            partner_info.partners_logo = img_url
            partner_info.save()
            return Response("ok", status=status.HTTP_201_CREATED)
        except Exception as e:
            print(f"Error: {e}")
            return Response(status=status.HTTP_400_BAD_REQUEST)


@permission_classes((IsAuthenticated,))
class ProjectUploadImg(viewsets.ViewSet):
    def create(self, request):
        try:
            # 获取上传的文件列表中的第一个文件
            img = request.FILES.getlist('file')[0]

            # 确保文件名是唯一的，可以通过添加时间戳、UUID等方式实现
            img_name = img.name
            img_url = f"/media/project/{img_name}"

            # 保存图片到指定目录
            img_path = os.path.join(MEDIA_ROOT, "project", img_name)
            with open(img_path, 'wb') as f:
                for chunk in img.chunks():
                    f.write(chunk)

            # 返回包含图片URL的响应
            return Response({"url": img_url}, status=status.HTTP_201_CREATED)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)


@permission_classes((IsAuthenticated,))
class HonourImagesViewSet(viewsets.ViewSet):
    def create(self, request):
        try:
            img = request.FILES.getlist('file')[0]
            honour_id = request.data.get('id')
            honour_info = models.Honour.objects.get(id=honour_id)
            honour_name = honour_info.title

            # 使用 UUID 来生成唯一的文件名
            unique_filename = str(uuid.uuid4())
            extension = os.path.splitext(img.name)[1]  # 获取文件扩展名
            img_name = f"{honour_name}_{unique_filename}{extension}"
            img_url = f"/media/honour/{img_name}"

            # 确保目录存在
            os.makedirs(MEDIA_ROOT + "/honour/", exist_ok=True)

            # 打开原始图像并进行压缩
            image = Image.open(img)
            image_io = BytesIO()
            image.save(image_io, format=image.format, quality=70)  # 设置压缩质量为70%
            compressed_image = ContentFile(image_io.getvalue(), name=img_name)

            # 保存压缩后的图像
            with open(MEDIA_ROOT + "/honour/" + img_name, 'wb') as f:
                f.write(compressed_image.read())

            honour_info.image_url = img_url
            honour_info.save()
            return Response("ok", status=status.HTTP_201_CREATED)
        except Exception as e:
            # 可以在这里记录错误日志，以帮助调试
            print(f"Error: {e}")
            return Response(status=status.HTTP_400_BAD_REQUEST)


@api_view(['POST'])
@permission_classes((AllowAny,))
def upload_news_image(request):
    if request.method == 'POST' and request.FILES.get('file'):
        image = request.FILES['file']
        original_name = image.name

        # 确保存储目录存在
        image_directory = os.path.join(MEDIA_ROOT, 'news_images')
        if not os.path.exists(image_directory):
            os.makedirs(image_directory)

        # 生成唯一文件名以避免同名覆盖
        unique_name = f"{uuid.uuid4().hex}_{original_name}"
        image_path = os.path.join(image_directory, unique_name)

        try:
            # 打开原始图像并进行压缩
            with Image.open(image) as img:
                image_io = BytesIO()
                img.save(image_io, format=img.format, quality=70)  # 设置压缩质量为70%
                compressed_image = image_io.getvalue()

            # 保存压缩后的图像
            with open(image_path, 'wb') as f:
                f.write(compressed_image)

            # 生成完整的图片 URL（包括协议、域名和端口）
            current_site_url = '{}://{}'.format(request.scheme, request.get_host())
            image_url = f"/media/news_images/{unique_name}"

            # 按照指定格式构造 JSON 响应
            response_data = {
                "errno": 0,
                "data": [
                    {
                        "url": image_url,
                        "alt": original_name,  # 使用原始文件名作为 alt
                        "href": ""  # 如果有默认跳转链接，可以在此设置
                    }
                ]
            }

            return JsonResponse(response_data)

        except Exception as e:
            print(f"Error during image processing: {e}")
            return JsonResponse({"errno": 1, "data": []}, status=400)

    # 错误处理 - 在这里可以添加更多的错误信息和处理逻辑
    return JsonResponse({"errno": 1, "data": []}, status=400)


@permission_classes((AllowAny,))
class ThreeNewsView(viewsets.ViewSet):
    @action(detail=False, methods=['get'])
    def latest(self, request):
        news_type = request.query_params.get('type', 'performance')
        latest_news = News.objects.filter(type=news_type).order_by('-publish_date')[:3]

        processed_news = []
        for news in latest_news:
            soup = BeautifulSoup(news.content, 'lxml')
            full_text = soup.get_text()
            short_text = full_text[:300] + ('...' if len(full_text) > 300 else '')

            processed_news.append({
                'id': news.id,
                'title': news.title,
                'publish_date': news.publish_date,
                'short_content': short_text,
                'cover_image_url': news.cover_image_url,
                'create_time': news.create_time,
                'view_count': news.view_count
            })

        return Response(processed_news)


@permission_classes((AllowAny,))
class GetProductViewSet(viewsets.ViewSet):

    def list(self, request):

        paginator = Paginator(models.Products.objects.order_by('name'), 24)

        paginator_serializers = [ProductSerializer(page).data for page in paginator.page(1)]

        start = 0
        limit = 4

        part_product_list = []
        while True:
            part = paginator_serializers[start: limit]
            part_dict = dict()
            for index in range(len(part)):
                part_dict['name%s' % (index + 1)] = part[index].get('name')
                part_dict['item_num%s' % (index + 1)] = part[index].get('item_num')

            part_product_list.append(part_dict)
            start = limit
            limit = limit + 4

            if limit == 24:
                break

        return Response(part_product_list)


@permission_classes((AllowAny,))
class FilterProViewSet(viewsets.ViewSet):

    def list(self, request):
        search_value = request.GET.get('search_value')
        pro_name_list = []
        for obj in models.Products.objects.filter(Q(item_num__icontains=search_value)
                                                  | Q(name__icontains=search_value)):
            pro_name_list.append(obj.name + "[" + obj.item_num + "]")

        return Response(pro_name_list)


@permission_classes((AllowAny,))
class GetMappingViewSet(viewsets.ViewSet):

    def list(self, request):
        search_value = request.GET.get('search_value').split('[')[0]
        item_num = ''
        for obj in models.Products.objects.filter(Q(name=search_value) | Q(item_num=search_value)):
            item_num = obj.item_num
            break

        return Response(item_num)
